package sw6.visualschedule.persistence;

import com.j256.ormlite.android.apptools.OrmLiteBaseService;
import com.j256.ormlite.dao.Dao;

import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public abstract class AbstractDataRepo<T> extends OrmLiteBaseService<DatabaseHelper> {

    private final transient Class<T> mType;
    private transient Dao<T, Integer> mDao;
    private static final String LOG_NAME = "AbstractDataRepo";
    
    // TODO: See if this parameter can be removed and taken from the class type.
    public AbstractDataRepo(final Class<T> typeT) {
        super();
        mType = typeT;
    }
    
    @Override
    public IBinder onBind(final Intent intent) {
        return null;
    }
    
    /**
     * Returns an entity from it's id.
     * @param itemId the entity id.
     * @return the entity matching the id.
     */
    public T getById(final int itemId) {
        T result = null;
        
        try {
            result = getDao().queryForId(itemId);
        } catch (SQLException e) {
            Log.e("getById", e.getMessage());
            throw new RuntimeException(LOG_NAME, e);
        }
        
        return result;
    }
    
    /**
     * Returns a list of all entities.
     * @return a list of all entities.
     */
    public List<T> getAll() {
        List<T> result = new ArrayList<T>();
        
        try {
            result = getDao().queryForAll();
        } catch (SQLException e) {
        	throw new RuntimeException(LOG_NAME, e);
        }

        return result;
    }
    
    /**
     * Deletes an entity.
     * @param obj the entity to delete.
     */
    public void delete(final T obj) {
        try {
            getDao().delete(obj);
        } catch (SQLException e) {
        	throw new RuntimeException(LOG_NAME, e);
        }
    }
    
    /**
     * Deletes an entity from it's id.
     * @param itemId the id of the entity to delete.
     */
    public void delete(final int itemId) {
        try {
            final Collection<Integer> ids = new ArrayList<Integer>();
            ids.add(itemId);

            getDao().deleteIds(ids);   
        } catch (SQLException e) {
        	throw new RuntimeException(LOG_NAME, e);
        }
    }
    
    /**
     * Updates an entity in the database.
     * @param obj the entity to update.
     */
    public void update(final T obj) {
        try {
            getDao().update(obj);
        } catch (SQLException e) {
        	throw new RuntimeException(LOG_NAME, e);
        }
    }
    
    /**
     * Stores an entity in the database. 
     * @param obj the entity to create.
     */
    public void create(final T obj) {
        try {
            getDao().create(obj);
        } catch (SQLException e) {
        	throw new RuntimeException(LOG_NAME, e);
        }
    }
    
    protected Dao<T, Integer> getDao() {
        if (mDao == null) {
            try {
                mDao = getHelper().getDao(mType);
            } catch (SQLException e) {
            	throw new RuntimeException(LOG_NAME, e);
            }
        }
        
        return mDao;
    }
}
